/*
  LICENSE
  -------
Copyright 2005 Nullsoft, Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer. 

  * Redistributions in binary form must reproduce the above copyright notice,
    this list of conditions and the following disclaimer in the documentation
    and/or other materials provided with the distribution. 

  * Neither the name of Nullsoft nor the names of its contributors may be used to 
    endorse or promote products derived from this software without specific prior written permission. 
 
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR 
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/


//#include <afxwin.h>
#include <windows.h>
#include <shlobj.h>
#include <assert.h>

#include "resource.h"




//#include <afxdlgs.h>		// for property sheets, pages
#include <prsht.h>			// for property sheets, pages
//#include <ddraw.h>

#include "vis.h"

#include "milkdrop.h"
#include "configpanel.h"

// ---------GLOBAL OBJECTS---------
// ---------GLOBAL OBJECTS---------
// ---------GLOBAL OBJECTS---------
CMilkDropObj	*pg = NULL;				// THE MAIN GLOBAL OBJECT
//CSoundData		*pg_sound = NULL;		// GLOBAL OBJECT FOR UNIVERSAL ACCESS TO SOUND ANALYSIS
// ---------GLOBAL OBJECTS---------
// ---------GLOBAL OBJECTS---------
// ---------GLOBAL OBJECTS---------

int g_oldWinampShowState = SW_SHOWNORMAL;



// returns a winampVisModule when requested. Used in hdr, below
winampVisModule *getModule(int which);

// "member" functions
void config(struct winampVisModule *this_mod); // configuration dialog
int init(struct winampVisModule *this_mod);	   // initialization for module
int render1(struct winampVisModule *this_mod);  // rendering for module 1
void quit(struct winampVisModule *this_mod);   // deinitialization for module

// Module header, includes version, description, and address of the module retriever function
winampVisHeader hdr = { VIS_HDRVER, DLLDESC, getModule };

// first module (milkdrop)
winampVisModule mod1 =
{
	MODULEDESC,
	NULL,	// hwndParent
	NULL,	// hDllInstance
	0,		// sRate
	0,		// nCh
	30,		// latencyMS - delay between audio & video
	10,		// delayMS - winamp will make sure that at least this much time passes per frame.
	0,		// spectrumNch
	2,		// waveformNch
	{ 0, },	// spectrumData
	{ 0, },	// waveformData
	config,
	init,
	render1, 
	quit
};

// this is the only exported symbol. returns our main header.
// if you are compiling C++, the extern "C" { is necessary, so we just #ifdef it
#ifdef __cplusplus
extern "C" {
#endif
__declspec( dllexport ) winampVisHeader *winampVisGetHeader()
{
	return &hdr;
}
#ifdef __cplusplus
}
#endif

// getmodule routine from the main header. Returns NULL if an invalid module was requested,
// otherwise returns either mod1, mod2 or mod3 depending on 'which'.
winampVisModule *getModule(int which)
{
	switch (which)
	{
		case 0: return &mod1;
		//case 1: return &mod2;
		//case 2: return &mod3;
		default: return NULL;
	}
}

// configuration. Passed this_mod, as a "this" parameter. Allows you to make one configuration
// function that shares code for all your modules (you don't HAVE to use it though, you can make
// config1(), config2(), etc...)
void config(struct winampVisModule *this_mod)
{
	if (pg != NULL)
	{
		MessageBox( NULL, "Sorry - you can't configure MilkDrop while it's running.\r\nPlease stop MilkDrop and try again.", "Can't configure while running", MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL );
		return;
	}

	pg = new CMilkDropObj;

	pg->Init(this_mod->hwndParent, this_mod->hDllInstance);

	InitCommonControls(); // loads common controls DLL 

	// note: DialogBox is modal, but CreateDialog is modeless
	//CreateDialog(this_mod->hDllInstance, MAKEINTRESOURCE(IDD_CONFIG), NULL, (DLGPROC)ConfigDialogProc);
	DialogBox(this_mod->hDllInstance, MAKEINTRESOURCE(IDD_CONFIG), NULL,/*this_mod->hwndParent,*/ (DLGPROC)ConfigDialogProc);

	assert(pg != NULL);
	if (pg != NULL)
	{
		delete pg;
		pg = NULL;
	}
}

// initialization. Registers our window class, creates our window, etc. Again, this one works for
// both modules, but you could make init1() and init2()...
// returns 0 on success, 1 on failure.
int init(struct winampVisModule *this_mod)
{
	if (pg != NULL)
	{
		MessageBox( NULL, "Sorry - you can't run MilkDrop while it's already open\r\n(either running or being configured).\r\n\r\nPlease exit all instances of MilkDrop and try again.", "Multiple Instances Not Allowed", MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL );
		return 1;
	}

	// query winamp for its playback state
	int ret = SendMessage(this_mod->hwndParent, WM_USER, 0, 104); 
	// ret=1: playing, ret=3: paused, other: stopped

	if (ret != 1)
	{
		MessageBox( NULL, "MilkDrop can't run without music.\r\nPlease play some music, through Winamp, and then try running MilkDrop again.", "No music playing", MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_TASKMODAL );
		return 1;  // failure
	}

	if (pg != NULL)
	{
		delete pg;
		pg = NULL;
	}
	
	pg = new CMilkDropObj;

	pg->Init(this_mod->hwndParent, this_mod->hDllInstance);
	
	if (pg->GoFullScreen())
	{
		// success
		return 0;
	}
	else
	{
		pg->Finish();
		if (pg != NULL)
		{
			delete pg;
			pg = NULL;
		}

		// failure
		return 1;
	}
	
	// show the window
	//ShowWindow(pg->m_hMainWnd,SW_SHOWNORMAL);

	return 0;
}

// render function for oscilliscope. Returns 0 if successful, 1 if visualization should end.
int render1(struct winampVisModule *this_mod)
{
	assert(pg != NULL);

	pg->RenderFrame(this_mod->waveformData[0], this_mod->waveformData[1]);

	return 0;
}


// cleanup (opposite of init()). Destroys the window, unregisters the window class, nukes D3D
void quit(struct winampVisModule *this_mod)
{
	assert(pg != NULL);
	pg->Finish();
	if (pg != NULL)
	{
		delete pg;
		pg = NULL;
	}
}




